package com.detech.sboh.business.user.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.detech.sboh.base.annotation.Log;
import com.detech.sboh.base.annotation.ProductSwagger;
import com.detech.sboh.base.config.properties.HeadPictureProperties;
import com.detech.sboh.base.domain.R;
import com.detech.sboh.base.domain.RE;
import com.detech.sboh.base.enumtype.LogTypeEnum;
import com.detech.sboh.base.enumtype.ModuleEnum;
import com.detech.sboh.base.hibernate.user.entity.TbUser;
import com.detech.sboh.base.page.Page;
import com.detech.sboh.base.page.PageParam;
import com.detech.sboh.base.satoken.core.service.PermissionService;
import com.detech.sboh.base.satoken.utils.LoginHelper;
import com.detech.sboh.business.user.model.UserOrderModel;
import com.detech.sboh.business.user.service.UserService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

@RestController
@RequestMapping(value = "/user")
@Api(tags = "用户管理")
public class UserController {

    @Autowired
    private UserService userService;
    @Resource
    private PermissionService permissionService;
    @Autowired
    private HeadPictureProperties headPictureProperties;

    @ApiOperation(value = "添加用户", notes = "添加用户")
    @ApiOperationSupport( author = "方安伦")
    @SaCheckPermission("system:user:add")
    @ApiImplicitParams({
            @ApiImplicitParam(name="username",value="用户帐号",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true),
            @ApiImplicitParam(name="realname",value="真实姓名",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true),
            @ApiImplicitParam(name="age",value="年龄",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true)
    })
    @RequestMapping(value = "/addUser",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "添加用户", saveDB = true,showParam = "username")
    public RE addUser(String username, String realname, String age) {
        boolean existFlag = userService.isUsernameExist(username);
        if (existFlag) {
            return R.checkFail("该用户账号已经存在，请重新输入！");
        } else {
            userService.register(username,realname,Integer.parseInt(age));
            return R.ok();
        }
    }

    @ApiOperation("根据用户ID获取详细信息")
    @SaCheckPermission("system:user:query")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户ID", paramType = "query",dataTypeClass = String.class,required = true)
    })
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "根据用户ID获取详细信息", saveDB = false)
    @PostMapping(value = "/info")
    public RE<Map<String, Object>> getInfo(String userId) {
        // 角色权限
        Set<String> roles = permissionService.getUserRolePermission(userId);
        // 菜单权限
        Set<String> permissions = permissionService.getUserMenuPermission(userId);

        Map<String, Object> ajax = new HashMap<>();
        ajax.put("user", userService.findUserById(userId));
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return R.ok(ajax);
    }

    @ApiOperation(value = "修改用户信息", notes = "修改用户信息")
    @ApiOperationSupport( author = "方安伦")
    @SaCheckPermission("system:user:edit")
    @ApiImplicitParams({
            @ApiImplicitParam(name="id",value="用户ID",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true),
            @ApiImplicitParam(name="realname",value="真实姓名",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true),
            @ApiImplicitParam(name="age",value="年龄",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true),
            @ApiImplicitParam(name="status",value="帐号状态（0正常 1停用）",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true),
            @ApiImplicitParam(name="delFlag",value="删除标志（0代表存在 2代表删除）",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true)
    })
    @RequestMapping(value = "/updateUser",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "修改用户信息", saveDB = true,showParam = "id")
    public RE updateUser(String id,String username,String realname,String age,String status,String delFlag) {
        TbUser tbUser = userService.findUserById(id);
        if (tbUser == null) {
            return R.checkFail("该用户不存在！");
        } else {
            //用户帐号和密码不可在此修改
            tbUser.setUsername(null);
            tbUser.setPassword(null);

            tbUser.setRealname(realname);
            tbUser.setAge(new Integer(age));
            tbUser.setStatus(status);
            tbUser.setDelFlag(delFlag);
            userService.updateUser(tbUser);
            return R.ok();
        }
    }

    @ApiOperation(value = "修改用户密码", notes = "修改用户密码")
    @ApiOperationSupport( author = "方安伦")
    @SaCheckPermission("system:user:updatePwd")
    @ApiImplicitParams({
            @ApiImplicitParam(name="oldPassword",value="旧密码",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true),
            @ApiImplicitParam(name="newPassword",value="新密码",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true)
    })
    @RequestMapping(value = "/updateUserPwd",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "修改用户密码", saveDB = true,showParam = "id")
    public RE updateUserPwd(String oldPassword,String newPassword) {
        TbUser tbUser = userService.findUserById(LoginHelper.getUserId().toString());
        if (!BCrypt.checkpw(oldPassword, newPassword)) {
            return R.checkFail("修改密码失败，旧密码错误！");
        }
        if (BCrypt.checkpw(newPassword, newPassword)) {
            return R.checkFail("新密码不能与旧密码相同！");
        }
        tbUser.setPassword(BCrypt.hashpw(newPassword));
        userService.updateUser(tbUser);
        return R.ok();
    }

    @ApiOperation(value = "删除用户", notes = "删除用户")
    @ApiOperationSupport( author = "方安伦")
    @SaCheckPermission("system:user:remove")
    @ApiImplicitParams({
            @ApiImplicitParam(name="userId",value="用户ID",paramType = "query", dataTypeClass=String.class,required=true)
    })
    @RequestMapping(value = "/deleteUser",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.WARN,value = "删除用户", saveDB = true,showParam = "userId")
    public RE deleteUser(String userId) {
        if (userId.equals(LoginHelper.getUserId())) {
            return R.checkFail("当前用户不能删除");
        }
        userService.deleteUserById(userId);
        return R.ok();
    }

    @ApiOperation(value = "上传用户头像", notes = "上传用户头像")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="file",value="用户头像图片文件",dataType="__file", dataTypeClass = MultipartFile.class ,paramType = "query",required=true)
    })
    @RequestMapping(value = "/uploadHeadPicture",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "上传用户头像")
    public RE uploadHeadPicture(@RequestPart(name="file") MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            return R.fail("上传文件为空！");
        }
        String extension = FileUtil.extName(file.getOriginalFilename());
        if (!StrUtil.equalsAnyIgnoreCase(extension, headPictureProperties.getFileExt())) {
            return R.checkFail("文件格式不正确，请上传" + Arrays.toString(headPictureProperties.getFileExt()) + "格式");
        }
        if (file.getSize() > headPictureProperties.getFileSize()*1024*1024) {
            return R.checkFail("上传文件不能大于"+Math.round(headPictureProperties.getFileSize())+"M！");
        }
        userService.uploadHeadPicture(LoginHelper.getUserId().toString(),file);
        return R.ok();
    }

    @ApiOperation(value = "下载用户头像", notes = "下载用户头像")
    @ApiOperationSupport( author = "方安伦")
    @GetMapping(value="/downloadHeadPicture/{id}")
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "下载用户头像")
    public void downloadHeadPicture(HttpServletResponse response,@PathVariable(value = "id",required = true) String id) throws IOException {
        TbUser tbUser = userService.findUserById(id);
        if(tbUser==null){
            return ;
        }
        //设置下载文件名称
        String fileName = tbUser.getHeadPicture();
        //拼接文件存储路径
        String uploadFilePath = headPictureProperties.getFilePath();//得到上传文件主路径
        String filePath = uploadFilePath + tbUser.getHeadPicture();//得到文件的存储路径
        // 清空response
        response.reset();
        // 设置response的Header
        response.setCharacterEncoding("UTF-8");
        response.addHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
        long fileLength = new File(filePath).length();
        response.setHeader("Content-Length", String.valueOf(fileLength));
        response.setContentType("application/octet-stream;charset=UTF-8");
        //获取 response 的输出流，用来输出文件
        ServletOutputStream out = response.getOutputStream();
        //读取，以输入流的形式读取文件
        FileInputStream in = new FileInputStream(filePath);
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = in.read(buffer))!=-1) {
            out.write(buffer, 0, len);
        }
        out.flush();
    }

    @ApiOperation(value = "读取用户头像图片", notes = "读取用户头像图片")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="id",value="用户ID",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true)
    })
    @RequestMapping(value="/loadHeadPicture",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "读取用户头像图片")
    public void loadHeadPicture(String id) throws IOException {
        TbUser tbUser = userService.findUserById(id);
        if(tbUser==null){
            return ;
        }
        String uploadFilePath = headPictureProperties.getFilePath();//得到上传文件主路径
        String filePath = uploadFilePath + tbUser.getHeadPicture();//得到文件的存储路径
        FileInputStream inputStream = new FileInputStream(filePath);
        int len = inputStream.available();
        //byte数组用于存放图片字节数据
        byte[] buff = new byte[len];
        inputStream.read(buff);
        //关闭输入流
        inputStream.close();

        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = servletRequestAttributes.getResponse();
        //设置响应内容类型
        response.setContentType("image/*");
        ServletOutputStream out = response.getOutputStream();
        out.write(buff);
        out.flush();
        out.close();
    }

    @ApiOperation(value = "查询用户列表（实体数据返回）不分页", notes = "查询用户列表（实体数据返回）不分页")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="username",value="用户帐号",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=false),
            @ApiImplicitParam(name="realname",value="真实姓名",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=false)
    })
    @RequestMapping(value = "/loadUserListNoPage",method = RequestMethod.POST)
    @ProductSwagger
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "查询用户列表（实体数据返回）不分页", saveDB = true)
    public RE<TbUser> loadUserListNoPage(String username,String realname) {
        List<TbUser> userList = userService.loadUserListNoPage(username,realname);
        return R.ok(userList);
    }

    @ApiOperation(value = "查询用户列表（返回部分字段的Map数据）不分页", notes = "查询用户列表（返回部分字段的Map数据）不分页")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="username",value="用户帐号",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=false),
            @ApiImplicitParam(name="realname",value="真实姓名",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=false)
    })
    @ProductSwagger
    @RequestMapping(value = "/loadUserListMapNoPage",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "查询用户列表（返回部分字段的Map数据）不分页", saveDB = true)
    public RE<List> loadUserListMapNoPage(String username,String realname) {
        List userList = userService.loadUserListMapNoPage(username,realname);
        return R.ok(userList);
    }

    @ApiOperation(value = "查询用户列表（原生SQL）不分页，不带参数", notes = "查询用户列表（原生SQL）不分页，不带参数")
    @ApiOperationSupport( author = "方安伦")
    @ProductSwagger
    @RequestMapping(value = "/loadUserListSqlNoPage",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "查询用户列表（原生SQL）不分页，不带参数", saveDB = true)
    public RE<List> loadUserListSqlNoPage() {
        List userList = userService.loadUserListSqlNoPageNoParam();
        return R.ok(userList);
    }

    @ApiOperation(value = "查询用户列表（原生SQL）不分页，带参数", notes = "查询用户列表（原生SQL）不分页，带参数")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="username",value="用户帐号",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true)
    })
    @ProductSwagger
    @RequestMapping(value = "/loadUserListSqlNoPageParam",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "查询用户列表（原生SQL）不分页，带参数", saveDB = true)
    public RE<List> loadUserListSqlNoPage(String username) {
        List userList = userService.loadUserListSqlNoPageParam(username);
        return R.ok(userList);
    }

    @ApiOperation(value = "查询用户列表（实体数据返回）", notes = "查询用户列表（实体数据返回）")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="username",value="用户帐号",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=false),
            @ApiImplicitParam(name="realname",value="真实姓名",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=false)
    })
    @ProductSwagger
    @RequestMapping(value = "/loadUserList",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "查询用户列表（实体数据返回）", saveDB = true)
    public RE<Page<TbUser>> loadUserList(@Validated PageParam pageParam, String username, String realname) {
        Page userPage = userService.loadUserList(pageParam.build(),username,realname);
        return R.ok(userPage);
    }

    @ApiOperation(value = "查询用户列表（Map数据返回）", notes = "查询用户列表（Map数据返回）")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="username",value="用户帐号",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=false),
            @ApiImplicitParam(name="realname",value="真实姓名",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=false)
    })
    @ProductSwagger
    @RequestMapping(value = "/loadUserListMap",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "查询用户列表（Map数据返回）", saveDB = true)
    public RE<Page> loadUserListMap(@Validated PageParam pageParam,String username,String realname) {
        Page userPage = userService.loadUserListMap(pageParam.build(),username,realname);
        return R.ok(userPage);
    }

    @ApiOperation(value = "查询用户订单数量（Map数据返回）", notes = "查询用户订单数量（Map数据返回）")
    @ApiOperationSupport( author = "方安伦")
    @ProductSwagger
    @RequestMapping(value = "/loadUserOrderListMap",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "查询用户订单数量（Map数据返回）", saveDB = true)
    public RE<Page> loadUserOrderListMap(@Validated PageParam pageParam) {
        Page userPage = userService.loadUserOrderListMap(pageParam.build());
        return R.ok(userPage);
    }

    @ApiOperation(value = "查询用户订单数量（实体数据返回）", notes = "查询用户订单数量（实体数据返回）")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="username",value="用户帐号",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=false),
            @ApiImplicitParam(name="realname",value="真实姓名",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=false)
    })
    @ProductSwagger
    @RequestMapping(value = "/loadUserOrderList",method = RequestMethod.POST)
    @Log(model = ModuleEnum.USER_MANAGE,logType = LogTypeEnum.INFO,value = "查询用户订单数量（实体数据返回）", saveDB = true)
    public RE<Page<UserOrderModel>> loadUserOrderList(@Validated PageParam pageParam,String username,String realname) {
        Page userPage = userService.loadUserOrderList(pageParam.build(),username,realname);
        return R.ok(userPage);
    }
}
